using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;

namespace Glpt.Data
{
    /// <summary>
    /// Json数据类
    /// </summary>
    public class JsonDataTable
    {
        private string CONTENT = "";
        private string TABLE_NAME = "";
        private string[] FIELD_NAME = new string[] { };
        /// <summary>
        /// 初始化类的新实例
        /// </summary>
        /// <param name="content">内容</param>
        public JsonDataTable(string content)
        {
            CONTENT = content;
        }
        /// <summary>
        /// 初始化类的新实例
        /// </summary>
        /// <param name="content">内容</param>
        /// <param name="table_name">表名</param>
        /// <param name="field_name">字段名列表</param>
        public JsonDataTable(string content, string table_name, string field_name)
        {
            CONTENT = content;
            TABLE_NAME = table_name;
            FIELD_NAME = field_name.Trim().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
        }
        /// <summary>
        /// 转成数据表
        /// </summary>
        /// <returns>数据表</returns>
        public DataTable GetDataTable()
        {
            DataTable srcdt = new DataTable();
            if (TABLE_NAME.Length > 0)
            {
                string[] name_lsit = TABLE_NAME.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
                List<JObject> jarr = new List<JObject>();
                JContainer jct = JsonConvert.DeserializeObject<JContainer>(CONTENT);
                if (jct is JArray)
                {
                    foreach (JObject jo in jct)
                    {
                        jarr.Add(jo);
                    }
                }
                else if (jct is JObject)
                    jarr.Add((JObject)jct);
                for (int i = 0; i < name_lsit.Length; i++)
                {
                    string name = name_lsit[i];
                    List<JObject> jarr2 = new List<JObject>();
                    for (int j = 0; j < jarr.Count; j++)
                    {
                        foreach (JProperty jp in jarr[j].Properties())
                        {
                            if (name.Equals("*") || jp.Name.Equals(name))
                            {
                                if (jp.Value is JArray)
                                {
                                    JArray jarr3 = (JArray)jp.Value;
                                    foreach (JObject jo3 in jarr3)
                                        jarr2.Add(jo3);
                                }
                                else if (jp.Value is JObject)
                                    jarr2.Add((JObject)jp.Value);
                                else if (jp.Value is JValue)
                                    jarr2.Add(JObject.Parse(jp.Value.ToString()));
                            }
                        }
                    }
                    jarr = jarr2;
                }
                //把属性转成DataTable
                foreach (JObject jo in jarr)
                {
                    AddFieldAndValue(srcdt, jo, FIELD_NAME);
                }
            }
            else
            {
                srcdt = JsonStringToTable(CONTENT.Trim());
            }
            foreach (DataColumn dc in srcdt.Columns)
            {
                foreach (DataRow drd in srcdt.Rows)
                {
                    if (drd[dc.ColumnName].ToString().Length == 0)
                        drd[dc.ColumnName] = DBNull.Value;
                }
            }
            return srcdt;
        }
        /// <summary>
        /// 检测是否要获取的路径
        /// </summary>
        /// <param name="path">目标路径</param>
        /// <param name="jp">当前节点</param>
        /// <returns>是否要</returns>
        private static bool CheckPath(string path, JProperty jp)
        {
            if (jp.Value is JObject || jp.Value is JArray)
                return false;
            string path2 = jp.Path;
            if (path.Equals(path2))
                return true;
            string[] FIELD1 = path.Trim().Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
            string[] FIELD2 = path2.Trim().Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
            bool ret = true;
            for (int i = 0; i < FIELD1.Length && i < FIELD2.Length; i++)
            {
                if (FIELD1[i].Equals("*") && !(i == FIELD2.Length - 1 && (jp.Value is JObject)))
                    continue;
                else if (!FIELD1[i].Equals(FIELD2[i]) && !(FIELD2[i].StartsWith(FIELD1[i] + '[') && FIELD2[i].EndsWith("]")))
                {
                    ret = false;
                    break;
                }
            }
            return ret;
        }
        private static void AddFieldAndValue(DataTable dt, JObject jo, string[] fields)
        {
            if (jo == null) return;
            DataRow dr = dt.NewRow();
            foreach (JProperty jp in jo.Properties())
            {
                if (jp.Value is JArray)
                    continue;
                if (jp.Value is JObject)
                {
                    //补字段(下一级)
                    if (fields != null && fields.Length > 0)
                    {
                        foreach (string fieldname in fields)
                        {
                            JObject jo2 = (JObject)jp.Value;
                            foreach (JProperty jp2 in jo2.Properties())
                            {
                                if (CheckPath(fieldname, jp2))
                                {
                                    if (!dt.Columns.Contains(jp2.Name))
                                        dt.Columns.Add(jp2.Name);
                                    dr[jp2.Name] = jp2.Value.ToString();
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (!dt.Columns.Contains(jp.Name))
                        dt.Columns.Add(jp.Name);
                    dr[jp.Name] = jp.Value.ToString();
                }
            }
            //补字段(上一级)
            if (fields != null && fields.Length > 0)
            {
                JContainer jc = jo.Parent;
                while (jc != null)
                {
                    if (jc is JObject)
                    {
                        JObject jo2 = (JObject)jc;
                        foreach (string fieldname in fields)
                        {
                            foreach (JProperty jp2 in jo2.Properties())
                            {
                                if (CheckPath(fieldname, jp2))
                                {
                                    if (!dt.Columns.Contains(jp2.Name))
                                        dt.Columns.Add(jp2.Name);
                                    dr[jp2.Name] = jp2.Value.ToString();
                                }
                            }
                        }
                    }
                    jc = jc.Parent;
                }
            }
            dt.Rows.Add(dr);
        }
        /// <summary>
        /// 字符串转成数据表
        /// </summary>
        /// <param name="contents">内容</param>
        /// <returns>数据表</returns>
        public static DataTable JsonStringToTable(string contents)
        {
            DataTable srcdt = new DataTable();
            if (contents.StartsWith("["))
            {
                JArray jarr = JsonConvert.DeserializeObject<JArray>(contents);
                foreach (JObject jo in jarr)
                {
                    AddFieldAndValue(srcdt, jo, null);
                }
            }
            else
            {
                JObject jo = JsonConvert.DeserializeObject<JObject>(contents);
                AddFieldAndValue(srcdt, jo, null);
            }
            return srcdt;
        }
        /// <summary>
        /// 字符串转成字典
        /// </summary>
        /// <param name="contents">内容</param>
        /// <returns>字典</returns>
        public static Dictionary<string, string> JsonStringToDictionary(string contents)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();
            JObject jt = JsonConvert.DeserializeObject<JObject>(contents);
            if (jt != null)
            {
                foreach (JProperty jp in jt.Properties())
                {
                    if (!(jp.Value is JObject))
                        dict.Add(jp.Name, jp.Value.ToString());
                }
            }
            return dict;
        }
        /// <summary>
        /// 数据表转成字符串
        /// </summary>
        /// <param name="dt">数据表</param>
        /// <returns>内容</returns>
        public static string TableToJsonString(DataTable dt)
        {
            return JsonConvert.SerializeObject(dt);
        }
    }
}